﻿// Program: SmoothDrawModel.cs
//
// This library defines the domain of Unicode text drawing operations with anti-aliasing
// support and painting of interior regions with a 'middleground' color. All operations are
// performed on a GDI+ System.Drawing.Bitmap.
//
// This solves the problem of drawing shapes where the interior region of the shape
// must have a different color than the background.  For example, drawing a Unicode chess
// character of a white piece will produce an image with a black outline and an interior
// color the same as the color of the square, instead of white.
//
// The drawing and filling operations both support anti-aliasing.  Symbols are centered
// vertically and horizontally.
//
// Operations are performed on the extended GDI+ System.Drawing.Bitmap class.  GDI+ bitmaps
// do not natively support transparency for clipboard and file I/O so for transparency
// support, use the PNG format.
//

using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using GdiPlusExtensions;

namespace SmoothDraw
{
    public delegate void PicChangedEventHandler ();

    public class SmoothDrawModel
    {
        private Rectangle fgBounds;
        public Bitmap Pic;
        public float FontFactor = 0.8F;

        public Color BgColor = Color.Transparent;
        public Color FgColor = Color.Black;
        public Color MgColor = Color.White;

        public string Text = "Q";
        public string FontName = "Tahoma";

        public Size PicSize = new Size (256, 256);

        public event PicChangedEventHandler PicChanged;

        public void DrawPicture ()
        {
            Bitmap pic = new Bitmap (PicSize.Width, PicSize.Height);
            pic.Fill (Color.Transparent);

            using (var gx = Graphics.FromImage (pic))
            using (var fgBrush = new SolidBrush (FgColor))
            {
                gx.SmoothingMode = SmoothingMode.HighQuality;
                gx.TextRenderingHint = TextRenderingHint.AntiAlias;

                Font font = new Font (FontName, PicSize.Height * FontFactor, FontStyle.Regular, GraphicsUnit.Pixel);
                StringFormat format = StringFormat.GenericTypographic;
                var measure = gx.MeasureString (Text, font, PicSize.Width, format);
                var origin = new Point ((int) ((PicSize.Width - measure.Width) / 2), PicSize.Height/-10);

                gx.DrawString (Text, font, fgBrush, origin, format);
            }

            //fgBounds = pic.GetOpaqueBounds();
            fgBounds = pic.Center ();

            if (BgColor.A == 0)
            {
                if (MgColor.A != 0)
                    pic.FlattenMiddleground (MgColor, fgBounds);
            }
            else
            {
                pic.FillOutside (BgColor, fgBounds);
                pic.FloodFillAlphaFromRectangle (BgColor, fgBounds);

                if (MgColor.A > 0)
                    pic.Flatten (MgColor);
            }

            Pic = pic;
            OnPicChanged();
        }

        public void FillMiddleground ()
        {
            if (Pic != null)
            {
                Pic.FlattenMiddleground (MgColor, fgBounds);
                OnPicChanged();
            }
        }

        public void Flood (int x, int y)
        {
            if (Pic != null && MgColor.A == 0xff)
            {
                Pic.FloodFill (MgColor, x, y);
                OnPicChanged();
            }
        }

        public void FloodTransparency (int x, int y)
        {
            if (Pic != null && MgColor.A == 0xff)
            {
                Color target = Pic.GetPixel (x, y);
                Pic.FloodFillAlpha (MgColor, x, y);
                OnPicChanged();
            }
        }

        public void OnPicChanged ()
        {
            if (PicChanged != null)
                PicChanged();
        }
    }
}
